package Bubble;

import java.awt.geom.Point2D;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

import Part.Part;
import Part.Parts;
import PathPoint.Path;

import com.golden.gamedev.Game;
import com.golden.gamedev.object.Sprite;
import com.golden.gamedev.object.SpriteGroup;

/**
 * Collection for Bubbles
 * @author Yin
 *
 */
public class Bubbles extends SpriteGroup
{
	private Game myGame;
	private static Path myPath;
	private Parts myParts;
	private LinkedList<Bubble> myBubbleList;
	private int myEpisode;
	
	//private final int COLOR_NUM = 7;
	private String[] COLORS = {"resources/blue.png",
			"resources/red.png",
			"resources/green.png",
			"resources/orange.png",
			"resources/purple.png",
			"resources/cyan.png",
			"resources/white.png"};
	
	public Bubbles(Game game, Path path, Parts parts)
	{
		super("Bubbles");
		myGame = game;
		myPath = path;
		myParts = parts;
		myBubbleList = new LinkedList<Bubble>();
		myEpisode = 1;
	}
	
	public Parts getParts()
	{
		return myParts;
	}
	
	public Path getPath()
	{
		return myPath;
	}
	
	public boolean isFirst(Bubble bubble)
	{
		return myBubbleList.getFirst()==bubble;
	}
	
	public boolean isLast(Bubble bubble)
	{
		return myBubbleList.getLast()==bubble;
	}
	
	/**
	 * Get list of bubbles in this Sprite Group
	 * @return
	 */
	public LinkedList<Bubble> getList()
	{
		return myBubbleList;
	}
	
	public void addFirst(Bubble bubble)
	{
		myBubbleList.addFirst(bubble);
		this.add(0, bubble);
	}
	
	/**
	 * Add a bubble to the end of this sprite group and its list
	 * @param bubble
	 */
	public void add(Bubble bubble)
	{
		myBubbleList.add(bubble);
		this.add(bubble);
	}
	
	public void add(int index, Bubble bubble)
	{
		myBubbleList.add(index, bubble);
		this.add(bubble);
	}
	
	/**
	 * Remove the first bubble
	 */
	public void removeFirst()
	{
		myBubbleList.removeFirst();
		this.remove(0);
	}
	
	public void remove(Bubble bubble)
	{
		myBubbleList.remove(bubble);
		this.remove(bubble);
	}
	
	/**
	 * Get bubble at given index
	 * @param index
	 * @return
	 */
	public Bubble getBubble(int index)
	{
		return myBubbleList.get(index);
	}
	
	/**
	 * Get bubble located at the end of the list
	 * @return
	 */
	public Bubble getLastBubble()
	{
		return myBubbleList.getLast();
	}
	
	/**
	 * Randomly generate a bubble without providing value of episode
	 * @param totally_random
	 * @param bubbleList
	 * @return
	 */
	public Bubble getRandomBubble(boolean totally_random, List<Bubble> bubbleList)
	{
		return getRandomBubble(totally_random, myEpisode, bubbleList);
	}
	
	/**
	 * Randomly generate a bubble
	 * @param totally_random
	 * @param episode
	 * @param bubbleList
	 * @return
	 */
	public Bubble getRandomBubble(boolean totally_random, int episode, List<Bubble> bubbleList)
	{
		myEpisode = episode;
		int max = 3 + (myEpisode + 1) / 2;
		Bubble bub = new Bubble(myGame.getImage(COLORS[randInt(max)]));
		
		if (totally_random)
			return bub;
		
		while(true)
		{
			if (bubbleList.contains(bub))
				return bub;
			bub = new Bubble(myGame.getImage(COLORS[randInt(max)]));
		}
	}
	
	/**
	 * Get random int
	 * @param max
	 * @return
	 */
	private int randInt (int max)
    {
        return (int)(Math.random() * max);
    }
	
	/**
	 * Update bubble location
	 * @param path_t0
	 * @param bubble
	 */
	public static void updateBubbleLocation(double path_t0, Bubble bubble)
	{
		Point2D.Double tp = myPath.getPathPoint(path_t0+bubble.getT());
		bubble.setLocation(tp.x, tp.y);
	}
	
	/**
	 * When bubShot hits the bubble path, this method determines whether the adjacent are to burst
	 * @param idx
	 * @param bubShot
	 * @return
	 */
	public boolean adjIsGoingToBurst (int index, Bubble bubShot)
    {
        int idx = index;
		int i = 1;
        for (Bubble b = getBubble(idx); b != null; idx--)
            i++;
        idx = index;
        for (Bubble b = getBubble(idx); b != null; idx++)
            i++;
        return i >= 3;
    }
	
}
